using System;
using UnityEngine;
using UnityEngine.Events;

namespace GameBaseFramework.Attribute
{
    /// <summary>
    /// 整型数值
    /// </summary>
    [Serializable]
    public class IntAttribute : IEquatable<IntAttribute>
    {
        /// <summary>
        /// 用一次函数表示当前值和基础值之间的关系
        /// </summary>
        public LinearFunction ValueFunction = new();

        /// <summary>
        /// CurrentValue绑定的事件
        /// </summary>
        [HideInInspector]
        public UnityEvent<float, float> OnCurrentValueChange = new();

        /// <summary>
        /// 基础值
        /// </summary>
        [SerializeField]
        private int _BaseValue;
        public int BaseValue
        {
            get
            {
                return _BaseValue;
            }
            set
            {
                _BaseValue = value;
                ValueFunction.Apply(ref _CurrentValue, _BaseValue);
            }
        }

        /// <summary>
        /// 当前值
        /// </summary>
        [SerializeField]
        private int _CurrentValue;
        public int CurrentValue
        {
            get
            {
                return _CurrentValue;
            }
            set
            {
                OnCurrentValueChange.Invoke(_CurrentValue, value);
                _CurrentValue = value;
            }
        }

        /// <summary>
        /// 构造初始化
        /// </summary>
        /// <param name="value"></param>
        public IntAttribute(int value)
        {
            _BaseValue = value;
            _CurrentValue = value;
        }

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="intAttribute"></param>
        public IntAttribute(IntAttribute intAttribute)
        {
            _BaseValue = intAttribute.BaseValue;
            _CurrentValue = intAttribute.CurrentValue;
        }



        /// <summary>
        /// 构造初始化
        /// </summary>
        /// <param name="value1"></param>
        /// <param name="value2"></param>
        public IntAttribute(int value1, int value2)
        {
            _BaseValue = value1;
            _CurrentValue = value2;
        }

        /// <summary>
        /// 构造初始化
        /// </summary>
        public IntAttribute()
        {
            _BaseValue = 0;
            _CurrentValue = 0;
        }

        /// <summary>
        /// 强制赋值而不触发属性访问器
        /// </summary>
        /// <param name="data"></param>
        /// <param name="value"></param>
        public void Set(int BaseValue, int CurrentValue)
        {
            this._BaseValue = BaseValue;
            this._CurrentValue = CurrentValue;
        }

        #region 重写==和!=同时也要重写Equals()和GetHashCode()
        public override bool Equals(object obj)
        {
            return Equals(obj as IntAttribute);
        }

        public bool Equals(IntAttribute other)
        {
            return other != null &&
                   _BaseValue == other._BaseValue &&
                   BaseValue == other.BaseValue &&
                   _CurrentValue == other._CurrentValue &&
                   CurrentValue == other.CurrentValue;
        }

        public override int GetHashCode()
        {
            return HashCode.Combine(_BaseValue, BaseValue, _CurrentValue, CurrentValue);
        }
        #endregion

        /// <summary>
        /// 强转
        /// </summary>
        /// <param name="value"></param>
        public static explicit operator int(IntAttribute value)
        {
            return value.BaseValue;
        }

        /// <summary>
        /// ==
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator ==(IntAttribute x, IntAttribute y)
        {
            return x.Equals(y);
        }
        /// <summary>
        /// ==
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator !=(IntAttribute x, IntAttribute y)
        {
            return !x.Equals(y);
        }

        /// <summary>
        /// ==
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator ==(IntAttribute x, int y)
        {
            return (x._CurrentValue == y);
        }

        /// <summary>
        /// ==
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator !=(IntAttribute x, int y)
        {
            return (x._CurrentValue != y);
        }

        public static bool operator >(IntAttribute x, IntAttribute y) => (x._CurrentValue > y._CurrentValue);
        public static bool operator <(IntAttribute x, IntAttribute y) => (x._CurrentValue < y._CurrentValue);


    }
}
